package org.dimenfix.lib;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.dimenfix.setting.Constants;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Fixter {

	private String srcXmlPath;

	private Fixter(String srcXmlPath) {
		this.srcXmlPath = srcXmlPath;
	}

	/**
	 * 开始修正
	 */
	private void fix() {
		File srcFile = new File(srcXmlPath);
		if (srcFile.exists()) {
			if (!srcFile.isDirectory()) {
				String srcValueDir = srcFile.getParentFile().getName();
				int srcIndex = findIndex(srcValueDir); // 检索源value文件夹属于哪个分辨率
				if (srcIndex > -1) {
					// 按照源value文件所属的索引，获取需要修正的索引
					int[] indexs = getWaitingFixIndex(srcIndex);

					String rootFilePath = srcFile.getParentFile().getParentFile().getAbsolutePath();
					for (int targetIndex : indexs) {
						String targetPath = rootFilePath + "/" + Constants.VALUES_DIRS[targetIndex] + "/"
								+ Constants.DIMEN_NAME;
						copyFile(srcFile, targetPath);
						try {
							fixXml(targetPath, srcIndex, targetIndex);
						} catch (ParserConfigurationException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (SAXException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (TransformerException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				} else {
					System.out.println("没有收录适合的屏幕密度，无法适配");
				}
			} else {
				System.out.println("请将路径指向文件");
			}
		} else {
			System.out.println("路径不存在");
		}
	}

	/**
	 * 获取文件夹fileName
	 * 
	 * @param fileName
	 * @return 返回索引位置，找不到返回-1
	 */
	private int findIndex(String fileName) {
		for (int i = 0; i < Constants.VALUES_DIRS.length; i++) {
			if (Constants.VALUES_DIRS[i].equals(fileName)) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * 获取等待修正的索引列表
	 * 
	 * @param srcIndex
	 *            源索引
	 * @return 返回等待修正的索引列表
	 */
	private int[] getWaitingFixIndex(int srcIndex) {
		int[] indexs = new int[Constants.VALUES_DIRS.length - 1];
		for (int i = 0; i < srcIndex; i++) {
			indexs[i] = i;
		}
		for (int i = srcIndex + 1; i < Constants.VALUES_DIRS.length; i++) {
			indexs[i - 1] = i;
		}
		return indexs;
	}

	/**
	 * 复制文件
	 * 
	 * @param srcFile
	 *            源文件
	 * @param targetFilePath
	 *            目标路径
	 * @return 如果复制成功返回true，否则返回false
	 */
	private boolean copyFile(File srcFile, String targetFilePath) {
		return copyFile(srcFile, targetFilePath, true);
	}

	/**
	 * 复制单个文件
	 * 
	 * @param srcFile
	 *            待复制的文件
	 * @param targetFilePath
	 *            目标文件路径
	 * @param overlay
	 *            如果目标文件存在，是否覆盖
	 * @return 如果复制成功返回true，否则返回false
	 */
	private boolean copyFile(File srcFile, String targetFilePath, boolean overlay) {

		// 判断源文件是否存在
		if (!srcFile.exists()) {
			System.out.println("源文件：" + srcFile + "不存在！");
			return false;
		} else if (!srcFile.isFile()) {
			System.out.println("复制文件失败，源文件：" + srcFile + "不是一个文件！");
			return false;
		}

		// 判断目标文件是否存在
		File destFile = new File(targetFilePath);
		if (destFile.exists()) {
			// 如果目标文件存在并允许覆盖
			if (overlay) {
				// 删除已经存在的目标文件，无论目标文件是目录还是单个文件
				new File(targetFilePath).delete();
			}
		} else {
			// 如果目标文件所在目录不存在，则创建目录
			if (!destFile.getParentFile().exists()) {
				// 目标文件所在目录不存在
				if (!destFile.getParentFile().mkdirs()) {
					// 复制文件失败：创建目标文件所在目录失败
					return false;
				}
			}
		}

		// 复制文件
		int byteread = 0; // 读取的字节数
		InputStream in = null;
		OutputStream out = null;

		try {
			in = new FileInputStream(srcFile);
			out = new FileOutputStream(destFile);
			byte[] buffer = new byte[1024];

			while ((byteread = in.read(buffer)) != -1) {
				out.write(buffer, 0, byteread);
			}
			return true;
		} catch (FileNotFoundException e) {
			return false;
		} catch (IOException e) {
			return false;
		} finally {
			try {
				if (out != null)
					out.close();
				if (in != null)
					in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 修正单个xml文件
	 * 
	 * @param xmlPath
	 * @param srcIndex
	 * @param targetIndex
	 * 
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 * @throws TransformerException
	 */
	private void fixXml(String xmlPath, int srcIndex, int targetIndex)
			throws ParserConfigurationException, SAXException, IOException, TransformerException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setIgnoringElementContentWhitespace(true);
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(new File(xmlPath));

		// NodeList nodeList = document.getElementsByTagName("dimen");
		// int nodeListLength = nodeList.getLength();
		// for (int i = 0 ; i < nodeListLength ; i++) {
		// System.out.println(nodeList.item(i).getTextContent());
		// }

		Node node = document.getChildNodes().item(0);
		NodeList nodeList = node.getChildNodes();
		int nodeListLength = nodeList.getLength();
		String srcValueString = null;
		float srcValue = 0;
		for (int i = 0; i < nodeListLength; i++) {
			node = nodeList.item(i);
			srcValueString = node.getTextContent();
			for (String unit : Constants.DIMEN_UNITS) {
				try {
					srcValue = getFloatValue(srcValueString, unit);
				} catch (Exception ex) {
					ex.printStackTrace();
					continue;
				}
//				if (srcValue >= 0) {
					node.setTextContent(calculateDP(srcValue, srcIndex, targetIndex) + unit);
//				} else {
//					node.setTextContent(-calculateDP(srcValue, srcIndex, targetIndex) + unit);
//				}
			}
		}

		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer ts = tf.newTransformer();
		ts.transform(new DOMSource(document), new StreamResult(new File(xmlPath)));

		System.out.println(xmlPath + "修正完毕");
	}

	private float getFloatValue(String valueString, String unit) throws Exception {
		try {
			int index = valueString.indexOf(unit);
			if (index > 0 && index == valueString.length() - unit.length()) {
				return Float.parseFloat(valueString.substring(0, valueString.length() - 2));
			} else {
				throw (new Exception("unit doesn't match"));
			}
		} catch (Exception ex) {
			throw (ex);
		}
	}

	private float calculateDimen(float sourceDimen, int sourceIndex, int targetIndex) {
		return (float) (Math.round((sourceDimen * Constants.DENSITYS[sourceIndex] / Constants.WIDTHS[sourceIndex])
				* Constants.WIDTHS[targetIndex] / Constants.DENSITYS[targetIndex] * 100) / 100f);
	}

	private float calculateDP(float sourceDP, int sourceIndex, int targetIndex) {
		return (float) (Math.round((sourceDP * Constants.DENSITYS[sourceIndex] / Constants.WIDTHS[sourceIndex])
				* Constants.WIDTHS[targetIndex] / Constants.DENSITYS[targetIndex] * 100) / 100f);
	}

	/**
	 * 执行修正
	 * 
	 * @param resPath
	 */
	public static void fix(String resPath) {
		Fixter fixter = new Fixter(resPath);
		fixter.fix();
	}
}
